import { ComponentResolveContext, DomService, FormBindingType, SchemaService } from '@farris/designer-services';
import { BuilderHTMLElement } from '@farris/designer-element';
import FdTableTdComponent from './fd-table-td';

export default class FdTableEmptyTdComponent extends FdTableTdComponent {

    /**
     * 判断是否可以接收拖拽新增的子级控件
     */
    canAccepts(sourceElement: BuilderHTMLElement, targetElement?: BuilderHTMLElement, sourceContainer?: BuilderHTMLElement): boolean {
        const serviceHost = this.options.designerHost;
        const dragResolveService = serviceHost.getService('DragResolveService');
        const resolveContext = dragResolveService.getComponentResolveContext(sourceElement, this);


        // 接收实体树中拖拽来的字段，需要判断是否属于当前组件绑定的实体
        if (resolveContext.sourceType === 'field') {
            const schemaService = serviceHost.getService('SchemaService') as SchemaService;
            const fieldInfo = schemaService.getFieldByIDAndVMID(resolveContext.bindingTargetId, this.viewModelId);
            if (!fieldInfo || !fieldInfo.schemaField) {
                return false;
            } else {
                return true;
            }
        }
        // 接收工具箱中拖拽来的输入类控件
        if (resolveContext.sourceType === 'control') {
            return resolveContext.controlCategory === 'input';
        }

        // 单元格之间的拖拽，需要判断是否为同一个table的单元格
        if (resolveContext.sourceType === 'move' && sourceContainer) {
            const sourceTdComponent = sourceContainer && sourceContainer.componentInstance;

            if (!sourceTdComponent || !sourceTdComponent.parent || sourceTdComponent.parent.id !== this.parent.id) {
                return false;
            }
            // 为了进入拖拽drop方法，暂时为childrenContents赋值
            sourceContainer.childrenContents = [];
            return true;

        }
        return false;
    }


    /**
     * 点击单元格后将同组的单元格都加上边框
     */
    afterComponentClicked() {
        const { tdElements: tdElementsInSameGroup, activeEditorTdElement } = this.parent.getTdElementsInSameGroup(this.component.groupId);

        if (!tdElementsInSameGroup || !activeEditorTdElement) {
            return;
        }
        // 增加边框
        const currentSelectedElements = document.getElementsByClassName('dgComponentSelected');
        for (const ele of Array.from(currentSelectedElements)) {
            ele.classList.remove('dgComponentSelected');
        }
        tdElementsInSameGroup.forEach(td => {
            td.classList.add('dgComponentSelected');
        });
    }

    /**
     * 触发整个面板的刷新
     */
    rebuild(): Promise<any> {
        return this.parent.rebuild();
    }

    /**
     * 单元格接收新控件后事件(来源为控件工具箱或者实体树)
     * @param componentResolveContext 新控件构造信息
     */
    afterAcceptNewChildElement(componentResolveContext: ComponentResolveContext) {
        if (!componentResolveContext.bindingSourceContext) {
            return;
        }


        // 根据字段信息组装单元格编辑器信息
        const editor = this.resolveTdEditorFromBindingContext(componentResolveContext);

        // 当前目标单元格是编辑器
        if (this.component.tdType === 'editor') {
            this.component.editor = editor;
            this.setLabelTdProperty();

        } else if (this.component.tdType === 'staticText' && this.component.staticText) {
            // 当前目标单元格是标签
            this.component.staticText.text = editor.title || '';
            this.component.staticText.require = editor.require === true;

            this.setEditorTdProperty(editor);
        }

        // 切换到单元格的属性面板
        this.parent.emit('componentClicked', { componentInstance: this, needUpdatePropertyPanel: true });

    }

    /**
     * 根据字段信息组装单元格编辑器信息
     * @param componentResolveContext 新控件构造信息
     */
    private resolveTdEditorFromBindingContext(componentResolveContext: ComponentResolveContext) {
        // 获取绑定字段或变量
        let bindingType;
        let selectedField;
        const variableFieldNode = componentResolveContext.bindingSourceContext.variableFieldNode;
        if (variableFieldNode) {
            bindingType = FormBindingType.Variable;
            selectedField = variableFieldNode;
        }
        const entityFieldNode = componentResolveContext.bindingSourceContext.entityFieldNode;
        if (entityFieldNode) {
            bindingType = FormBindingType.Form;
            selectedField = entityFieldNode;
        }

        // 设置单元格编辑器
        const controlCreatorSerivice = this.options.designerHost.getService('ControlCreatorService');
        const domService = this.options.designerHost.getService('DomService');

        const hasStateMachine = domService.module.stateMachines && domService.module.stateMachines.length > 0;
        let editor;
        if (bindingType === FormBindingType.Form) {
            editor = controlCreatorSerivice.createTableTdControlBySchemaFeild(selectedField, componentResolveContext.controlType);
        } else {
            editor = controlCreatorSerivice.createTableTdControlByVariable(selectedField, componentResolveContext.controlType);
        }
        if (!editor.readonly && hasStateMachine) {
            editor.readonly = '!viewModel.stateMachine[\'editable\']';
        }

        return editor;
    }
    /**
     * 拖拽滑进单元格时，将同组的单元格都增加drag-over的样式，在视觉上让用户认为标签单元格和编辑器单元格为一个整体
     */
    onDragOver() {
        const { tdElements: tdElementsInSameGroup } = this.parent.getTdElementsInSameGroup(this.component.groupId);
        if (!tdElementsInSameGroup) {
            return;
        }

        tdElementsInSameGroup.forEach(td => {
            if (td.className && !td.className.includes('drag-over')) {
                td.classList.add('drag-over');
            }
        });
    }

    /**
     * 拖拽滑过离开单元格时，将同组的单元格都移除drag-over的样式，在视觉上让用户认为标签单元格和编辑器单元格为一个整体
     */
    onDragOut() {
        const { tdElements: tdElementsInSameGroup } = this.parent.getTdElementsInSameGroup(this.component.groupId);
        if (!tdElementsInSameGroup) {
            return;
        }
        tdElementsInSameGroup.forEach(td => {
            if (td.className) {
                td.className = td.className.replace('drag-over', '');
            }

        });
    }

    /**
     * 单元格之间拖拽后事件
     * @param elemnt 目标单元格元素
     * @param sourceElement 源标签单元格元素
     */
    onAcceptMovedChildElement(elemnt: BuilderHTMLElement, sourceElement: BuilderHTMLElement) {
        // sourceElement.componentInstance是源单元格实例，需要获取源单元格同组的编辑器单元格实例，并将绑定信息设置到当前新单元格中
        const sourceLableTdComponentInstance = sourceElement.componentInstance;
        if (!sourceLableTdComponentInstance) {
            return;
        }

        const { activeEditorTdElement: sourceActiveEditorTdElement } = this.parent.getTdElementsInSameGroup(sourceLableTdComponentInstance.component.groupId);
        const sourceEditorTdId = sourceActiveEditorTdElement && sourceActiveEditorTdElement.getAttribute('id');
        if (!sourceEditorTdId) {
            return;
        }
        let sourceTdEditor;

        // 1、清除源单元格及其对应编辑器的绑定信息
        if (sourceEditorTdId && this.parent.component && this.parent.component.rows) {
            for (const row of this.parent.component.rows) {
                if (row.columns && row.columns.length) {

                    const tdComponent = row.columns.find(co => co.tdType === 'editor' && co.id === sourceEditorTdId);
                    if (tdComponent) {
                        sourceTdEditor = Object.assign({}, tdComponent.editor);

                        tdComponent.editor = {
                            type: null,
                            binding: null
                        };
                        const labelComponent = row.columns.find(co => co.tdType === 'staticText' && co.id === sourceLableTdComponentInstance.id);
                        labelComponent.staticText = {
                            text: '',
                            require: false
                        };
                        break;
                    }

                }
            }
        }
        if (!sourceTdEditor) {
            return;
        }

        // 2、设置目标单元格的绑定信息
        if (this.component.tdType === 'editor') {     // 当前目标单元格是编辑器
            this.component.editor = sourceTdEditor;
            this.setLabelTdProperty();

        } else if (this.component.tdType === 'staticText' && this.component.staticText) {     // 当前目标单元格是标签
            this.component.staticText.text = sourceTdEditor.title || '';
            this.component.staticText.require = sourceTdEditor.require === true;

            this.setEditorTdProperty(sourceTdEditor);
        }

        // 若源单元格是选中状态，需要更新他的属性面板
        if (sourceActiveEditorTdElement.className.includes('dgComponentSelected')) {
            this.parent.emit('componentClicked', { componentInstance: sourceActiveEditorTdElement.componentInstance, needUpdatePropertyPanel: true });
        } else if (this.element.className.includes('dgComponentSelected')) {
            // 若当前目标单元格是选中状态，需要更新他的属性面板
            const { activeEditorTdElement: targetActiveEditorTdElement } = this.parent.getTdElementsInSameGroup(this.component.groupId);
            this.parent.emit('componentClicked', { componentInstance: targetActiveEditorTdElement.componentInstance, needUpdatePropertyPanel: true });
        }

        // 重构表格
        this.parent.rebuild();
    }

    /**
     * 设置同组编辑器单元格的属性
     * @param sourceTdEditor 编辑器绑定信息
     */
    private setEditorTdProperty(sourceTdEditor: any) {

        const { activeEditorTdElement: targetActiveEditorTdElement } = this.parent.getTdElementsInSameGroup(this.component.groupId);
        const targetEditorTdId = targetActiveEditorTdElement && targetActiveEditorTdElement.getAttribute('id');

        if (targetEditorTdId && this.parent.component && this.parent.component.rows) {
            for (const row of this.parent.component.rows) {
                if (row.columns && row.columns.length) {

                    const tdComponent = row.columns.find(co => co.tdType === 'editor' && co.id === targetEditorTdId);
                    if (tdComponent) {
                        tdComponent.editor = sourceTdEditor;
                        break;
                    }
                }
            }
        }
    }
}
